package org.microframework.base.core.security.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.microframework.base.core.security.annotation.Logical;
import org.microframework.base.core.security.annotation.RequiresLogin;
import org.microframework.base.core.security.annotation.RequiresPermissions;
import org.microframework.base.core.security.annotation.RequiresRoles;
import org.microframework.base.core.security.exception.NotAuthorizedException;
import org.microframework.base.core.security.utils.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;

/**
 * 安全切面
 * 
 * 处理权限注解
 */
@Aspect
@Component
public class SecurityAspect {
    
    private static final Logger log = LoggerFactory.getLogger(SecurityAspect.class);
    
    /**
     * 处理RequiresLogin注解
     */
    @Before("@annotation(org.microframework.base.core.security.annotation.RequiresLogin) || " +
            "@within(org.microframework.base.core.security.annotation.RequiresLogin)")
    public void handleRequiresLogin(JoinPoint joinPoint) {
        // 获取方法上的注解，如果没有则获取类上的注解
        RequiresLogin requiresLogin = getAnnotation(joinPoint, RequiresLogin.class);
        if (requiresLogin != null) {
            SecurityUtils.ensureLoggedIn();
            log.debug("验证登录状态通过");
        }
    }
    
    /**
     * 处理RequiresRoles注解
     */
    @Before("@annotation(org.microframework.base.core.security.annotation.RequiresRoles) || " +
            "@within(org.microframework.base.core.security.annotation.RequiresRoles)")
    public void handleRequiresRoles(JoinPoint joinPoint) {
        // 获取方法上的注解，如果没有则获取类上的注解
        RequiresRoles requiresRoles = getAnnotation(joinPoint, RequiresRoles.class);
        if (requiresRoles != null) {
            // 先确保用户已登录
            SecurityUtils.ensureLoggedIn();
            
            // 验证角色
            String[] roles = requiresRoles.value();
            Logical logical = requiresRoles.logical();
            
            if (roles.length == 0) {
                return;
            }
            
            if (logical == Logical.AND) {
                // 必须拥有所有角色
                for (String role : roles) {
                    if (!SecurityUtils.hasRole(role)) {
                        log.warn("用户缺少角色: {}", role);
                        throw new NotAuthorizedException("缺少角色: " + role);
                    }
                }
                log.debug("验证角色通过(AND): {}", String.join(",", roles));
            } else {
                // 拥有任一角色即可
                for (String role : roles) {
                    if (SecurityUtils.hasRole(role)) {
                        log.debug("验证角色通过(OR): {}", role);
                        return;
                    }
                }
                log.warn("用户缺少任一角色: {}", String.join(",", roles));
                throw new NotAuthorizedException("缺少角色: " + String.join(" 或 ", roles));
            }
        }
    }
    
    /**
     * 处理RequiresPermissions注解
     */
    @Before("@annotation(org.microframework.base.core.security.annotation.RequiresPermissions) || " +
            "@within(org.microframework.base.core.security.annotation.RequiresPermissions)")
    public void handleRequiresPermissions(JoinPoint joinPoint) {
        // 获取方法上的注解，如果没有则获取类上的注解
        RequiresPermissions requiresPermissions = getAnnotation(joinPoint, RequiresPermissions.class);
        if (requiresPermissions != null) {
            // 先确保用户已登录
            SecurityUtils.ensureLoggedIn();
            
            // 验证权限
            String[] permissions = requiresPermissions.value();
            Logical logical = requiresPermissions.logical();
            
            if (permissions.length == 0) {
                return;
            }
            
            if (logical == Logical.AND) {
                // 必须拥有所有权限
                for (String permission : permissions) {
                    if (!SecurityUtils.hasPermission(permission)) {
                        log.warn("用户缺少权限: {}", permission);
                        throw new NotAuthorizedException("缺少权限: " + permission);
                    }
                }
                log.debug("验证权限通过(AND): {}", String.join(",", permissions));
            } else {
                // 拥有任一权限即可
                for (String permission : permissions) {
                    if (SecurityUtils.hasPermission(permission)) {
                        log.debug("验证权限通过(OR): {}", permission);
                        return;
                    }
                }
                log.warn("用户缺少任一权限: {}", String.join(",", permissions));
                throw new NotAuthorizedException("缺少权限: " + String.join(" 或 ", permissions));
            }
        }
    }
    
    /**
     * 从连接点获取注解
     * 
     * @param joinPoint 连接点
     * @param annotationClass 注解类
     * @param <T> 注解类型
     * @return 注解实例
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    private <T> T getAnnotation(JoinPoint joinPoint, Class<T> annotationClass) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        
        // 优先获取方法上的注解
        T annotation = null;
        if (method.isAnnotationPresent((Class) annotationClass)) {
            annotation = (T) method.getAnnotation((Class) annotationClass);
        }
        
        // 如果方法上没有注解，则尝试获取类上的注解
        if (annotation == null) {
            Class<?> targetClass = method.getDeclaringClass();
            if (targetClass.isAnnotationPresent((Class) annotationClass)) {
                annotation = (T) targetClass.getAnnotation((Class) annotationClass);
            }
        }
        
        return annotation;
    }
} 